// import { SphereGeometry, CylinderGeometry, Group, Mesh, MeshStandardMaterial } from "three";
// import { occtimportjs } from './occt-import-js.js';
import * as THREE from "three";
            // 读取JSON文件
async function loadJSON(jsonfile) {
    const jsonfilecontent=await fetch(jsonfile);//提取jsonfile文件
    return jsonfilecontent.json();
}
//
function meshmorph(meshmodel,IniPosition,dislacement,morphratio){
    // 更新顶点位置以实现变形
    const vertex = meshmodel.geometry.attributes.position.array;
    for (let i = 0; i < meshmodel.geometry.attributes.position.count; i++) {
             
             vertex[i*3]  =IniPosition[i*3]+dislacement[i * 3]*morphratio;
             vertex[i*3+1]=IniPosition[i*3+1]+dislacement[i*3+1]*morphratio;
             vertex[i*3+2]=IniPosition[i*3+2]+dislacement[i*3+2]*morphratio;
             }
         meshmodel.geometry.attributes.position.needsUpdate = true; // 标记顶点数据已更改
    return 0;
 }
// 核心函数：检测框选范围内的节点
function selectPointsInRect(points,rect,camera) {
    const positionAttr = points.geometry.attributes.position;
    const colorAttr = points.geometry.attributes.color;
    const matrixWorld = points.matrixWorld; // 点集的世界矩阵
    const selectedPointIndices = []; // 存储选中点的索引

    // 遍历每个点（每次步长3，对应x,y,z）
    for (let i = 0; i < positionAttr.count; i++) {
        // 获取点的本地坐标
        const point = [];   
        point.push(positionAttr.getX(i));
        point.push(positionAttr.getY(i));
        point.push(positionAttr.getZ(i));
        const flag=selectSPInRect(point,rect,camera,matrixWorld);
        // 将本地坐标转换为世界坐标（考虑点集的位置、旋转、缩放）
        // const worldPos = new THREE.Vector3(x, y, z).applyMatrix4(matrixWorld);
        // // 将世界坐标转换为屏幕坐标
        // const screenPos = worldPos.project(camera);
        // const screenX = (screenPos.x * 0.5 + 0.5) * window.innerWidth;
        // const screenY = (-screenPos.y * 0.5 + 0.5) * window.innerHeight;
        // 判断是否在框选范围内
        if (flag) {
            selectedPointIndices.push(i);
            // 标记选中的点为红色
            colorAttr.setXYZ(i, 1, 0, 0); // R=1, G=0, B=0
        }
    }
    colorAttr.needsUpdate = true; // 通知渲染器颜色已更新
    return selectedPointIndices;
} 
function selectSPInRect(point,rect,camera,matrixWorld) {
        // 将本地坐标转换为世界坐标（考虑点集的位置、旋转、缩放）
        const worldPos = new THREE.Vector3(point[0], point[1], point[2]).applyMatrix4(matrixWorld);
        // 将世界坐标转换为屏幕坐标
        const screenPos = worldPos.project(camera);
        const screenX = (screenPos.x * 0.5 + 0.5) * window.innerWidth;
        const screenY = (-screenPos.y * 0.5 + 0.5) * window.innerHeight;
        // 判断是否在框选范围内
        if (screenX >= rect.x1 && screenX <= rect.x2 && screenY >= rect.y1 && screenY <= rect.y2) {
            return true;
        }
        else{
            return false;
        }
}
//
function meshColorUpdate(meshmodel,newcolor){
    // 更新顶点位置以实现变形
    // console.log(meshmodel.geometry.attributes.color.count);
    for (let i = 0; i < meshmodel.geometry.attributes.color.count; i++) {
             const color = meshmodel.geometry.attributes.color.array;
             color[i*3]  =newcolor[i*3];
             color[i*3+1]=newcolor[i*3+1];
             color[i*3+2]=newcolor[i*3+2];
             }
    meshmodel.geometry.attributes.color.needsUpdate = true; // 标记顶点数据已更改
    return 0;
 }
// 
function mshAttributesProc(jsonData) {//根据网格json文件中节点部分的数据信息，创建并初始化网格属性信息集合
    let Attributedict={}
    if(jsonData.nodeCount<1){
        console.log('There is no points in this mesh model');
        return 1;
    }
    // console.log("jsonData:");
    // console.log(jsonData);
    var nodescoor=jsonData.geometry.initialNodes;
    var nnode=jsonData.geometry.nodeCount;
    var colorini=[];
    // var nodeidlist=[];
    //console.log('input all nodes:',nnode);
    for(var i = 0; i < nnode; i++){
        colorini.push(0,0,1);
        // nodeidlist.push(i+1);//仅是做了节点统计
    }
    Attributedict['nnode']=nnode; 
    Attributedict['pointsarray']=nodescoor;
    Attributedict['NodeIDs']=jsonData.geometry['originalNodeIds'];//仅是做了节点统计，留作他用
    Attributedict['colorsarray']=colorini;
    Attributedict['geometryGroups']=jsonData.geometry['geometryGroups'];
    // console.log(Attributedict['geometryGroups']);   
    return Attributedict;
}
function mshAttributesObjCreate(jsonData) {//根据网格json文件中节点部分的数据信息，创建并初始化网格属性信息对象
    let Attributedict={};
    if(jsonData.nodeCount<1){
        console.log('There is no points in this mesh model');
        return 1;
    }
    // console.log("jsonData:");
    // console.log(jsonData);
    var nodescoor=jsonData.geometry.initialNodes;
    var nnode=jsonData.geometry.nodeCount;
    var colorini=[];
    // var nodeidlist=[];
    //console.log('input all nodes:',nnode);
    for(var i = 0; i < nnode; i++){
        colorini.push(0,0,1);
    }
    
    Attributedict['nnode']=nnode; 
    Attributedict['pointsarray']=new THREE.BufferAttribute(new Float32Array(nodescoor), 3);
    Attributedict['NodeIDs']=jsonData.geometry['originalNodeIds'];//仅是做了节点统计，留作他用
    Attributedict['colorsarray']=new THREE.BufferAttribute(new Float32Array(colorini), 3);
    Attributedict['geometryGroups']=jsonData.geometry['geometryGroups'];
    // console.log(Attributedict['geometryGroups']);   
    return Attributedict;
}
function mshAttributesColorUpdate(Attributedict,lut,resField) {
    var color = new THREE.Color();
  
    for ( var i = 0; i < resField.length; i ++ ) {
  
    	  var colorValue = resField[ i ];
        // console.log('Field value:',colorValue)
    	  color.copy( lut.getColor( colorValue ) ).convertSRGBToLinear();
        // console.log('corresponding color value:',color)
        Attributedict.colorsarray.array[3*i]=color.r;
        Attributedict.colorsarray.array[3*i+1]=color.g;
        Attributedict.colorsarray.array[3*i+2]=color.b;
    }
    Attributedict.colorsarray.needsUpdate = true;
}
function AttributeMeshMorph(Attributedict,IniPosition,dislacement,morphratio){
    // 更新顶点位置以实现变形
    const vertex = Attributedict.pointsarray;
    for (let i = 0; i < Attributedict.nnode; i++) {
             
             vertex.array[i*3]  =IniPosition[i*3]+dislacement[i * 3]*morphratio;
             vertex.array[i*3+1]=IniPosition[i*3+1]+dislacement[i*3+1]*morphratio;
             vertex.array[i*3+2]=IniPosition[i*3+2]+dislacement[i*3+2]*morphratio;
             }
    Attributedict.pointsarray.needsUpdate = true; // 标记顶点数据已更改
    return 0;
 }
function removeModel(scene) {
    // 遍历场景中的所有子对象并移除
            while(scene.children.length > 0) { 
                const child = scene.children[0];
                scene.remove(child);
                
                // 如果子对象是网格（Mesh），还需释放几何体和材质
                if (child.isMesh) {
                    child.geometry.dispose();
                    if (child.material) {
                        if (Array.isArray(child.material)) {
                            child.material.forEach(m => m.dispose());
                        } else {
                            child.material.dispose();
                        }
                    }
                }
            }
    }
function clearGroup(group) {
  // 循环移除所有子对象
  while (group.children.length > 0) {
    const child = group.children.pop();
    group.remove(child);

    // 1. 释放 Mesh/Sprite 的资源
    if (child instanceof THREE.Mesh || child instanceof THREE.Sprite) {
      // 释放几何体（BufferGeometry/Geometry）
      if (child.geometry) {
        child.geometry.dispose(); // 关键：释放几何体显存
      }
      // 释放材质（若材质不再复用）
      if (child.material) {
        const materials = Array.isArray(child.material) ? child.material : [child.material];
        materials.forEach(material => {
          // 释放材质中的纹理
          if (material.map && typeof material.map.dispose === 'function') {
            material.map.dispose(); // 释放纹理显存
            material.map = null;
          }
          material.dispose(); // 释放材质
        });
        child.material = null;
      }
    }

    // 2. 递归清空子 Group（若有嵌套）
    if (child instanceof THREE.Group) {
      clearGroup(child); // 递归处理子 Group
    }

    // 3. 解除所有引用（帮助 GC 回收）
    child.parent = null;
  }
}
function vertexColorTrue(group) {
    // 遍历组中的所有子对象并翻转顶点颜色显示与否
            var i=0;
            while(i<group.children.length) { 
                const child = group.children[i];
                // console.log(child);
                if (child.isMesh || child.isLineSegments) {
                // child.material.vertexColors=!child.material.vertexColors;
                child.material.color=0x000000;
                // child.material.transparent = true; // 启用透明
                // child.material.opacity = 0;
                //        // 透明度设为 0（完全透明）
                child.material.vertexColors=true;
                child.material.needsUpdate = true;
                if (child.name=='meshFrame') {
                    child.material.vertexColors=false;
                }
                }
                // console.log('after reverse vertexColors:');
                // console.log(child.material.vertexColors);
                i=i+1;
            }
}
// 
function clearGUIFolder(folder) {
    //递归销毁所有控制器

    var Clength=folder.controllers.length;
    for (var i = 0; i <Clength; i++) {
        folder.controllers[0].destroy();//销毁控制器并移除 DOM
      }
    //folder.controllers.forEach(controller => {
    //  console.log(controller);
      //controller.destroy(); // 销毁控制器并移除 DOM
      //controller.destroy(); // 销毁控制器并移除 DOM
    //});
    folder.controllers.length = 0; // 清空控制器数组
}
function attributedictBoundingBox(Attributedict){//基于导入的一系列点的三维坐标值算出包络方盒子参数
  if (Attributedict.boundingBox && !Attributedict.pointsarray.needsUpdate) {
    return Attributedict.boundingBox;
  }
    const positionAttribute = Attributedict.pointsarray;
    // const positionAttribute =meshmodel. geometry.getAttribute('position');
    Attributedict.boundingBox = new THREE.Box3().setFromBufferAttribute(positionAttribute);
    return Attributedict.boundingBox;
}
function BoxParaCreate(pointsarray,BoxPara){//基于导入的一系列点的三维坐标值算出包络方盒子参数
    //pointsarray导入的一系列点的三维坐标值，一维数组形式[....]
    //BoxPara对象，用来保存一系列点所形成长方形盒子的参数，主要是盒子尺寸和中心点坐标。
    const positionAttribute = new THREE.BufferAttribute(new Float32Array(pointsarray), 3);
    // const positionAttribute =meshmodel. geometry.getAttribute('position');
    BoxPara.boundingBox = new THREE.Box3().setFromBufferAttribute(positionAttribute);
    BoxPara.boxsize = BoxPara.boundingBox.getSize(new THREE.Vector3());
    BoxPara.boxcenter = BoxPara.boundingBox.getCenter(new THREE.Vector3());
    return 0;
}
function camerazoommid(camera,BoxPara){//基于方盒子参数重新设定摄像头camera参数
    const fov = camera.fov * (Math.PI / 180);
    const distance = Math.max(BoxPara.boxsize.x, BoxPara.boxsize.y, BoxPara.boxsize.z) / (2 * Math.tan(fov / 2));
    camera.position.copy(BoxPara.boxcenter).add(new THREE.Vector3(0, 0, distance * 1.2));
    camera.lookAt(BoxPara.boxcenter);
    camera.updateProjectionMatrix();
    return 0;
}

// 核心工具函数：模型居中（基于包围盒）
function centerModel(group,Attributedict) {
  // 计算模型的包围盒
  // const boundingBox = computeBoxFromVerticesCached(Attributedict);
  const boundingBox = attributedictBoundingBox(Attributedict);
  // console.log("boundingBox in centerModel:",boundingBox);
  // 计算包围盒中心
  const center = new THREE.Vector3();
  boundingBox.getCenter(center);
  // 模型整体平移，让中心对齐世界原点
  group.position.sub(center);
}
//核心工具函数：模型包围盒尺寸
function getModelSize(Attributedict) {
  const boundingBox = attributedictBoundingBox(Attributedict);
  const size = new THREE.Vector3();
  boundingBox.getSize(size);
  return size;
}
const getExtension = (filename) =>filename.match(/\.([0-9a-z]+)$/i)?.[1] || '';//获取文件名后缀
function isScientificNumber(str) {//判断字符串是否为纯数字
  if (typeof str !== 'string') return false;
  return /^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(str);
}
export{loadJSON,mshAttributesProc,removeModel,clearGUIFolder,meshmorph,BoxParaCreate,camerazoommid};
export{vertexColorTrue,meshColorUpdate,getModelSize,centerModel,clearGroup};
export{mshAttributesObjCreate,mshAttributesColorUpdate,AttributeMeshMorph,attributedictBoundingBox};
export{getExtension,isScientificNumber};